﻿Imports System.Collections.Generic
Imports System.Linq
Imports MvvmFoundation.Wpf

''' <summary>
''' Represents an item in a graph.
''' </summary>
Public Class Node
    Inherits ObservableObject

#Region "Constructor"

    Public Sub New(ByVal id As String, ByVal locationX As Double, ByVal locationY As Double)
        Me.NodeDependencies = New List(Of Node)
        'Me.CircularDependencies = New List(Of CircularDependency)
        Me.LocationX = locationX
        Me.LocationY = locationY
        Me.ID = id
    End Sub

#End Region ' Constructor

#Region "Properties"

    'Private _CircularDependencies As List(Of CircularDependency)
    'Public Property CircularDependencies As List(Of CircularDependency)
    '    Get
    '        Return _CircularDependencies
    '    End Get
    '    Private Set(ByVal value As List(Of CircularDependency))
    '        _CircularDependencies = value
    '    End Set
    'End Property

    'Public ReadOnly Property HasCircularDependency As Boolean
    '    Get
    '        Return Me.CircularDependencies.Any()
    '    End Get
    'End Property

    Private _ID As String
    Public Property ID As String
        Get
            Return _ID
        End Get
        Private Set(ByVal value As String)
            _ID = value
        End Set
    End Property

    Private _locationX As Double
    Public Property LocationX As Double
        Get
            Return _locationX
        End Get
        Set(ByVal value As Double)
            If (value = _locationX) Then Return

            _locationX = value
            MyBase.RaisePropertyChanged("LocationX")

        End Set
    End Property

    Private _LocationY As Double
    Public Property LocationY As Double
        Get
            Return _LocationY
        End Get
        Set(ByVal value As Double)
            If (value = _LocationY) Then Return

            _LocationY = value
            MyBase.RaisePropertyChanged("LocationY")

        End Set
    End Property

    Private _NodeDependancies As List(Of Node)
    Public Property NodeDependencies As List(Of Node)
        Get
            Return _NodeDependancies
        End Get
        Private Set(ByVal value As List(Of Node))
            _NodeDependancies = value
        End Set
    End Property

    Private _NodeWidth As Double = 100
    Public Property NodeWidth As Double
        Get
            Return _NodeWidth
        End Get
        Set(ByVal value As Double)
            _NodeWidth = value
            MyBase.RaisePropertyChanged("NodeWidth")
        End Set
    End Property

    Private _NodeHeight As Double = 30
    Public Property NodeHeight As Double
        Get
            Return _NodeHeight
        End Get
        Set(ByVal value As Double)
            _NodeHeight = value
            MyBase.RaisePropertyChanged("NodeHeight")
        End Set
    End Property

#End Region ' Properties

#Region "Methods"

    'public List<CircularDependency> FindCircularDependencies()
    '{
    '    if (this.NodeDependencies.Count == 0)
    '        return null;

    '    var circularDependencies = new List<CircularDependency>();

    '    var stack = new Stack<NodeInfo>();
    '    stack.Push(new NodeInfo(this));

    '            While (stack.Any())
    '    {
    '        var current = stack.Peek().GetNextDependency();
    '        if (current != null)
    '        {
    '            if (current.Node == this)
    '            {
    '                var nodes = stack.Select(info => info.Node);
    '                circularDependencies.Add(new CircularDependency(nodes));
    '            }
    '                    Else
    '            {
    '                bool visited = stack.Any(info => info.Node == current.Node);
    '                        If (!visited) Then
    '                    stack.Push(current);
    '            }
    '        }
    '                        Else
    '        {
    '            stack.Pop();
    '        }
    '    }

    '    return circularDependencies;
    '}

    Private Class NodeInfo

        Public Sub New(ByVal node As Node)
            Me.Node = node
            _index = 0
        End Sub

        Private _Node As Node
        Public Property Node As Node
            Get
                Return _Node
            End Get
            Private Set(ByVal value As Node)
                _Node = value
            End Set
        End Property

        Public Function GetNextDependency() As NodeInfo
            If (_index < Me.Node.NodeDependencies.Count) Then
                Dim nextNode = Me.Node.NodeDependencies(_index)
                _index += 1
                Return New NodeInfo(nextNode)
            End If
            Return Nothing
        End Function

        Dim _index As Integer
    End Class

#End Region ' Methods

End Class